#ifndef MODEL_RENDER_H
#define MODEL_RENDER_H

#include <string.h>
#include <fstream>
#include <cstdlib>
#include <iostream>
#include <map>
#include <vector>

#include "GLSL/GLSL_helper.h"
#include "glm/glm.hpp"
#include "glm/gtc/matrix_transform.hpp"
#include "glm/gtc/type_ptr.hpp"
#include "MatrixStack/MStackHelp.h"

#include "RenderManager.h"

#include <GL/gl.h>
#include <GL/glu.h>

// Assimp Headers
#include <Importer.hpp>     // C++ importer interface
#include <scene.h>          // Output data structure
#include <postprocess.h>    // Post processing flags

class ModelRender {
    // Rendering Vars
    RenderManager manager;   
    std::vector<MeshInfo> meshes;
    vec3 color;
    std::vector<glm::vec3> list;

    // Transforms vars
    vec3 translate;
    vec3 scale;
    vec3 rotateAxis;
    float rotateAngle;
    
    // Animation Vars
    bool isAnimated;
    int currentAnimation;
    float currentAnimationTime;
    
    // Texture Vars
    GLuint texture;
    
    // ASSIMP Vars
    const aiScene* assimpScene;
    Assimp::Importer assimpImporter;

    private:
        template<class T>
        void GenerateBuffers(GLuint* handle, std::vector<T> data);
        bool InitFromScene(const aiScene* pScene, const std::string& filename);
        void UpdateAnimation(unsigned int animationIndex, float timeStep);
        void UpdateVertices();
        
    public:
        ModelRender(bool isAnimated);
        
        // Setters
        void SetManager(RenderManager newManager) { manager = newManager; }
        void SetTexture(GLuint textPtr) { texture = textPtr; }
        void SetAnimation(int newAnim) { currentAnimation = newAnim; }
        void SetColor(vec3 newColor) { color = newColor; } 
        void ResetAnimationTime() { currentAnimationTime = 0.0f; }
        
        // Getters
        std::vector<glm::vec3> GetVertices();
        
        // Stack Functions
        void StackStack() { manager.StartStack(); }
        void EndStack() { manager.EndStack(); }
        void Translate(glm::vec3 offset) { translate = offset; }
        void Scale(glm::vec3 ratio) { scale = ratio; }
        void Rotate(float newAngle, glm::vec3 newAxis) { rotateAngle = newAngle; rotateAxis = newAxis; }
        
        // Main Functions
        void Initialize(const std::string& filename);
        void Draw(float dt);
        void Dispose();
};

#endif
